<template>
  <div class="line">
    <h1>11ß</h1>
    <div id="container"></div>
  </div>
</template>

<script>
import G6 from '@antv/g6';
import rawData from "./dataG6Two.js"
const {
  Util,
  registerBehavior,
  registerEdge,
  registerNode
} = G6;


export default {
  name: "G6",
  data() {
    return {

    }
  },
  created() { },
  mounted() {
    this.initG6();
  },
  methods: {
    //  业务数据拓扑图
    initG6() {
      if (graph) {
        graph.destroy()
      }
      //是否展示
      const isInBBox = (point, bbox) => {
        const { x, y } = point;
        const { minX, minY, maxX, maxY } = bbox;
        return x < maxX && x > minX && y > minY && y < maxY;
      };

      const itemHeight = 30;
      let graph = null
      const container = document.getElementById('container');
      const width = container.scrollWidth || 800
      const height = container.scrollHeight || 800
      registerBehavior("dice-er-scroll", {
        getDefaultCfg() {
          return {
            multiple: true,
          };
        },
        getEvents() {
          return {
            itemHeight: 50,
            wheel: "scorll",
            click: "click",
            "node:mousemove": "move",
          };
        },

        scorll(e) {
          e.preventDefault();
          const { graph } = this;
          const nodes = graph.getNodes().filter((n) => {
            const bbox = n.getBBox();

            return isInBBox(graph.getPointByClient(e.clientX, e.clientY), bbox);
          });

          const x = e.deltaX || e.movementX;
          let y = e.deltaY || e.movementY;
          if (!y && navigator.userAgent.indexOf("Firefox") > -1)
            y = (-e.wheelDelta * 125) / 3;

          if (nodes) {
            const edgesToUpdate = new Set();
            nodes.forEach((node) => {
              const model = node.getModel();
              if (model.attrs.length < 2) {
                return;
              }
              const idx = model.startIndex || 0;
              let startX = model.startX || 0.5;
              let startIndex = idx + y * 0.02;
              startX -= x;
              if (startIndex < 0) {
                startIndex = 0;
              }
              if (startX > 0) {
                startX = 0;
              }
              if (startIndex > model.attrs.length - 1) {
                startIndex = model.attrs.length - 1;
              }
              graph.updateItem(node, {
                startIndex,
                startX,
              });
              node.getEdges().forEach((edge) => edgesToUpdate.add(edge));
            });

            edgesToUpdate.forEach((edge) => edge.refresh());
          }
        },

        // },
        //点击事件
        click(e) {
          const {
            graph
          } = this;
          const {
            y
          } = e;
          const item = e.item;
          const shape = e.shape;
          if (!item) {
            return;
          }
          const model = item.getModel();
          //节点的展开和折叠的事件
          if (shape.get("name") === "collapse") {
            graph.updateItem(item, {
              collapsed: true,
              size: [300, 50],
            });
            setTimeout(() => graph.layout(), 100);
          } else if (shape.get("name") === "expand") {
            graph.updateItem(item, {
              collapsed: false,
              size: [300, 500],
            });
            setTimeout(() => graph.layout(), 100);
          }
        },
        move(e) {
          return
          const name = e.shape.get("name");
          const item = e.item;
          if (name && name.startsWith("item")) {
            this.graph.updateItem(item, {
              selectedIndex: Number(name.split("-")[1]),
            });
          } else {
            this.graph.updateItem(item, {
              selectedIndex: NaN,
            });
          }
        },
      });

      registerEdge("dice-er-edge", {
        draw(cfg, group) {
          const edge = group.cfg.item;
          const sourceNode = edge.getSource().getModel();
          const targetNode = edge.getTarget().getModel();

          const sourceIndex = sourceNode.attrs.findIndex(
            (e) => e.key === cfg.sourceKey
          );

          const sourceStartIndex = sourceNode.startIndex || 0;

          let sourceY = 15;

          if (!sourceNode.collapsed && sourceIndex > sourceStartIndex - 1) {
            sourceY = 30 + (sourceIndex - sourceStartIndex + 0.5) * 30;
            sourceY = Math.min(sourceY, 300);
          }

          const targetIndex = targetNode.attrs.findIndex(
            (e) => e.key === cfg.targetKey
          );

          const targetStartIndex = targetNode.startIndex || 0;

          let targetY = 15;

          if (!targetNode.collapsed && targetIndex > targetStartIndex - 1) {
            targetY = (targetIndex - targetStartIndex + 0.5) * 30 + 30;
            targetY = Math.min(targetY, 300);
          }

          const startPoint = {
            ...cfg.startPoint
          };
          const endPoint = {
            ...cfg.endPoint
          };

          startPoint.y = startPoint.y + sourceY;
          endPoint.y = endPoint.y + targetY;

          let shape;
          if (sourceNode.id !== targetNode.id) {
            shape = group.addShape("path", {
              attrs: {
                stroke: "#5B8FF9",
                path: [
                  ["M", startPoint.x, startPoint.y],
                  [
                    "C",
                    endPoint.x / 3 + (2 / 3) * startPoint.x,
                    startPoint.y,
                    endPoint.x / 3 + (2 / 3) * startPoint.x,
                    endPoint.y,
                    endPoint.x,
                    endPoint.y,
                  ],
                ],
                endArrow: true,
              },
              name: "path-shape",
            });
          } else if (!sourceNode.collapsed) {
            let gap = Math.abs((startPoint.y - endPoint.y) / 3);
            if (startPoint["index"] === 1) {
              gap = -gap;
            }
            shape = group.addShape("path", {
              attrs: {
                stroke: "#5B8FF9",
                path: [
                  ["M", startPoint.x, startPoint.y],
                  [
                    "C",
                    startPoint.x - gap,
                    startPoint.y,
                    startPoint.x - gap,
                    endPoint.y,
                    startPoint.x,
                    endPoint.y,
                  ],
                ],
                endArrow: true,
              },
              name: "path-shape",
            });
          }

          return shape;
        },
        afterDraw(cfg, group) {
          const labelCfg = cfg.labelCfg || {};
          const edge = group.cfg.item;
          const sourceNode = edge.getSource().getModel();
          const targetNode = edge.getTarget().getModel();
          if (sourceNode.collapsed && targetNode.collapsed) {
            return;
          }
          const path = group.find(
            (element) => element.get("name") === "path-shape"
          );

          const labelStyle = Util.getLabelPosition(path, 0.5, 0, 0, true);
          const label = group.addShape("text", {
            attrs: {
              ...labelStyle,
              text: cfg.label || '',
              fill: "#000",
              textAlign: "center",
              stroke: "#fff",
              lineWidth: 1,
            },
          });
          label.rotateAtStart(labelStyle.rotate);
        },
      });

      registerNode("dice-er-box", {
        draw(cfg, group) {
          const width = 250;
          const height = 316;
          const itemCount = 10;
          const boxStyle = {
            stroke: "#096DD9",
            radius: 4,
          };

          const {
            attrs = [],
            startIndex = 0,
            selectedIndex,
            collapsed,
            icon,
          } = cfg;
          const list = attrs;
          const afterList = list.slice(
            Math.floor(startIndex),
            Math.floor(startIndex + itemCount - 1)
          );
          const offsetY = (0.5 - (startIndex % 1)) * itemHeight + 30;

          group.addShape("rect", {
            attrs: {
              fill: boxStyle.stroke,
              height: 30,
              width,
              radius: [boxStyle.radius, boxStyle.radius, 0, 0],
            },
            draggable: true,
          });

          let fontLeft = 12;

          if (icon && icon.show !== false) {
            group.addShape("image", {
              attrs: {
                x: 8,
                y: 8,
                height: 16,
                width: 16,
                ...icon,
              },
            });
            fontLeft += 18;
          }

          group.addShape("text", {
            attrs: {
              y: 22,
              x: fontLeft,
              fill: "#fff",
              text: cfg.label,
              fontSize: 12,
              fontWeight: 500,
            },
          });

          group.addShape("rect", {
            attrs: {
              x: 0,
              y: collapsed ? 30 : 300,
              height: 15,
              width,
              fill: "#eee",
              radius: [0, 0, boxStyle.radius, boxStyle.radius],
              cursor: "pointer",
            },
            name: collapsed ? "expand" : "collapse",
          });

          group.addShape("text", {
            attrs: {
              x: width / 2 - 6,
              y: (collapsed ? 30 : 300) + 12,
              text: collapsed ? "+" : "-",
              width,
              fill: "#000",
              radius: [0, 0, boxStyle.radius, boxStyle.radius],
              cursor: "pointer",
            },
            name: collapsed ? "expand" : "collapse",
          });

          const keyshape = group.addShape("rect", {
            attrs: {
              x: 0,
              y: 0,
              width,
              height: collapsed ? 45 : height,
              ...boxStyle,
            },
            draggable: true,
          });

          if (collapsed) {
            return keyshape;
          }

          const listContainer = group.addGroup({});
          listContainer.setClip({
            type: "rect",
            attrs: {
              x: -8,
              y: 30,
              width: width + 16,
              height: 300 - 30,
            },
          });
          listContainer.addShape({
            type: "rect",
            attrs: {
              x: 1,
              y: 30,
              width: width - 2,
              height: 300 - 30,
              fill: "#fff",
            },
            draggable: true,
          });

          if (list.length > itemCount) {
            const barStyle = {
              width: 4,
              padding: 0,
              boxStyle: {
                stroke: "#00000022",
              },
              innerStyle: {
                fill: "#00000022",
              },
            };

            listContainer.addShape("rect", {
              attrs: {
                y: 30,
                x: width - barStyle.padding - barStyle.width,
                width: barStyle.width,
                height: height - 30,
                ...barStyle.boxStyle,
              },
            });

            const indexHeight =
              afterList.length > itemCount ?
                (afterList.length / list.length) * height :
                10;

            listContainer.addShape("rect", {
              attrs: {
                y: 30 +
                  barStyle.padding +
                  (startIndex / list.length) * (height - 30),
                x: width - barStyle.padding - barStyle.width,
                width: barStyle.width,
                height: Math.min(height, indexHeight),
                ...barStyle.innerStyle,
              },
            });
          }
          if (afterList) {
            afterList.forEach((e, i) => {
              const isSelected =
                Math.floor(startIndex) + i === Number(selectedIndex);
              let {
                key = "", type
              } = e;
              if (type) {
                key += " - " + type;
              }
              const label = key.length > 26 ? key.slice(0, 24) + "..." : key;

              listContainer.addShape("rect", {
                attrs: {
                  x: 1,
                  y: i * itemHeight - itemHeight / 2 + offsetY,
                  width: width - 4,
                  height: itemHeight,
                  radius: 2,
                  lineWidth: 1,
                  cursor: "pointer",
                },
                name: `item-${Math.floor(startIndex) + i}-content`,
                draggable: true,
              });

              if (!cfg.hideDot) {
                listContainer.addShape("circle", {
                  attrs: {
                    x: 0,
                    y: i * itemHeight + offsetY,
                    r: 3,
                    stroke: boxStyle.stroke,
                    fill: "white",
                    radius: 2,
                    lineWidth: 1,
                    cursor: "pointer",
                  },
                });
                listContainer.addShape("circle", {
                  attrs: {
                    x: width,
                    y: i * itemHeight + offsetY,
                    r: 3,
                    stroke: boxStyle.stroke,
                    fill: "white",
                    radius: 2,
                    lineWidth: 1,
                    cursor: "pointer",
                  },
                });
              }

              listContainer.addShape("text", {
                attrs: {
                  x: 12,
                  y: i * itemHeight + offsetY + 6,
                  text: label,
                  fontSize: 12,
                  fill: "#000",
                  fontFamily: "Avenir,-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol",
                  full: e,
                  fontWeight: isSelected ? 500 : 100,
                  cursor: "pointer",
                },
                name: `item-${Math.floor(startIndex) + i}`,
              });
            });
          }



          return keyshape;
        },
        getAnchorPoints() {
          return [
            [0, 0],
            [1, 0],
          ];
        },
      });

      //数据渲染
      const dataTransform = (data) => {
        console.log(data, 'ç')
        const nodes = []; //渲染的节点
        const edges = [];//链接线的配置
        if (data && data.length) {
          data.map((node) => {
            //添加需要渲染的节点
            nodes.push({
              ...node
            });
            // 如果有子节点的话
            if (node.attrs) {
              node.attrs.forEach((attr) => {
                // 如果子节点有连接点的话
                if (attr.relation) {
                  attr.relation.forEach((relation) => {
                    // edges用来保存链接点的数据
                    edges.push({
                      source: node.id, //谁（父级）
                      target: relation.nodeId,//指向谁（父级）
                      sourceKey: attr.key, //谁（子集）
                      targetKey: relation.key,//指向谁（子集）
                      label: relation.label,
                    });
                  });
                }
              });
            }else{
              // console.log(node)
              //  // 如果没有子节点的话
              // if(node.relation){
              //   node.relation.forEach((relation) => {
              //      console.log(relation,'')
              //     });
              // }
            }
          });
        }
        return {
          nodes,
          edges,
        };
      }


      graph = new G6.Graph({
        container: 'container',
        width,
        height,
        defaultNode: {
          size: [300, 400],
          type: 'dice-er-box',
          color: '#5B8FF9',
          style: {
            fill: '#9EC9FF',
            lineWidth: 3,
          },
          labelCfg: {
            style: {
              fill: 'black',
              fontSize: 20,
            },
          },
        },
        defaultEdge: {
          type: 'dice-er-edge',
          style: {
            stroke: '#e2e2e2',
            lineWidth: 4,
            endArrow: true,
          },
        },
        modes: {
          default: ['dice-er-scroll', 'drag-node', 'drag-canvas'],
        },
        layout: {
          type: 'dagre',
          rankdir: 'LR',//从左至右布局；
          align: 'UL',//对齐到左上角；
          controlPoints: true,
          nodesepFunc: () => 0.5,
          ranksepFunc: () => 0.5,
        },
        animate: true,
      })
      graph.data(dataTransform(rawData));

      graph.render();
    }
  }
}
</script>
<style lang="less" scoped>
.line {
  width: 100%;
  height: 100%;
}
</style>
